﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Extjs_ReGSharp.Exceptions;

namespace Extjs_ReGSharp.Criteria
{
	internal abstract class BaseCriteria<T, TType> : ICriteria<T>
	{
		#region Data Memebers

		private TypePropertyWrapper<T> m_Property;

		private bool m_IsMemberValid = true;

		#endregion

		#region Protected Data Members

		private TType m_CriteriaValue;

		#endregion

		#region Private Methods

		private bool TypesDontMatch()
		{
			return typeof(TType) != m_Property.FieldType;
		}

		#endregion

		#region Properties

		public string FieldName
		{
			get
			{
				return m_Property.Property.Name;
			}
		}

		public TType CriteriaValue
		{
			get
			{
				return m_CriteriaValue;
			}
		}

		#endregion

		#region Constructor

		protected BaseCriteria(string field, TType value)
		{
			m_Property = new TypePropertyWrapper<T>(field);

			if ((!m_Property.IsMemberValid) || TypesDontMatch())
			{
				m_IsMemberValid = false;

				return;
			}

			m_CriteriaValue = value;
		}

		#endregion

		#region Abstract Methods

		protected abstract bool IsValid(TType instanceValue);

		#endregion

		#region Public Methods

		public bool IsValid(T instance)
		{
			if (!m_IsMemberValid)
			{
				throw new FieldNotFoundException();
			}

			TType instanceValue = GetValueFromInstance(instance);

			bool result = IsValid(instanceValue);

			return result;
		}

		public TType GetValueFromInstance(T instance)
		{
			TType result = (TType)m_Property.Property.GetValue(instance, null);

			return result;
		}

		#endregion
	}
}
